package com.mxl.rabbitmq.config.base;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.time.LocalTime;

/**
 * @author MXL
 * RabbitTemplate.ConfirmCallback接口: 回调用来确定消息到达交换器
 * RabbitTemplate.ReturnsCallback接口: 消息路由到队列失败时被调用
 * @date 2021/9/14 0014
 **/
@Configuration
@Slf4j
public class RabbitConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {

    @Autowired
    RabbitTemplate rabbitTemplate;

    /**
     * 定义 initRabbitTemplate 方法并添加 @PostConstruct 注解，
     * 在该方法中为 rabbitTemplate 分别配置这两个 Callback。
     */
    @PostConstruct
    public void initRabbitTemplate() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    /**
     * 回调用来确定消息是否
     * @param correlationData correlation data for the callback.
     * @param ack true for ack, false for nack
     * @param cause An optional cause, for nack, when available, otherwise null.
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        log.info("到达交换机的时间戳: {}", LocalTime.now());
        if (ack) {
            log.info("ConfirmCallback接口的confirm():消息成功到达交换器, cause: {}", correlationData, cause);
        } else {
            log.error("ConfirmCallback接口的confirm():消息发送失败, 消息未达到exchange, cause: {}", correlationData, cause);
        }
    }

    /**
     * 消息路由到队列失败时被调用
     *
     * @param returned the returned message and metadata.
     */
    @Override
    public void returnedMessage(ReturnedMessage returned) {
        log.error("消息未成功路由到队列: {}", JSON.toJSONString(returned));
    }
}
